#include "shoesGUI.h"

#include<qlabel.h>
#include <qpushbutton.h>
#include <qfiledialog.h>
#include <qmenubar.h>
#include <qimage.h>
#include <qmessagebox.h>
#include <qthread.h>
#include <qdebug.h>


using namespace cv;
using namespace std;

shoesGUI::shoesGUI(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    ui.centralWidget->setEnabled(false);
    qsSaveDir = "./";
    QMenuBar* bar = menuBar();
    this->setMenuBar(bar);                      // 将菜单栏放入主窗口
    QMenu* fileMenu = bar->addMenu("File");     // 创建父节点
    QAction* saveDirAction = fileMenu->addAction("Save resault");     // 设置名字
    connect(saveDirAction, &QAction::triggered, this, [=]() {
        if (resaultImg.empty())
        {
            QMessageBox::warning(this,
                tr("There is nothing to save !"),
                tr("There is nothing to save !"));
            return;
        }

        qsSaveDir = QFileDialog::getSaveFileName(this,
            tr("Get save file name"),
            "./",
            tr("")
        );
        if (qsSaveDir.isEmpty())
        {
            QMessageBox::information(this,
                tr("Get save file name failed !"),
                tr("Get save file name failed !"));
            qsSaveDir = "./";
            return;
        }
        });
    saveDirAction->setEnabled(false);
    //fileMenu->addSeparator();                                      // 添加分割线
    QAction* AddTemplateAction = fileMenu->addAction("Add/Change template");     // 设置名字
    connect(AddTemplateAction, &QAction::triggered, this, [=]() {
        qsTemplatePath = QFileDialog::getOpenFileName(this,
            tr(" "),
            "./",
            tr(" "));
        templateImg = imread(qsTemplatePath.toStdString(), IMREAD_GRAYSCALE);
        if (templateImg.empty())
        {
            QMessageBox::information(this,
                tr("Open Image failed !"),
                tr("Open Image failed !"));
            return;
        }
        template_curve = templateImg.clone();
        Mat showTemplateImg;
        cvtColor(templateImg, showTemplateImg, COLOR_GRAY2BGR);
        QSize labelSize = ui.templateLabel->size();
        labelSize.setWidth(labelSize.width() * 0.9);
        labelSize.setHeight(labelSize.height() * 0.9);
        QImage qtFrame = QImage((const uchar*)showTemplateImg.data, showTemplateImg.cols, showTemplateImg.rows, showTemplateImg.step, QImage::Format_RGB888);
        QPixmap pixmap = QPixmap::fromImage(qtFrame).scaled(labelSize);
        ui.templateLabel->setPixmap(pixmap);
        ui.templateLabel->setScaledContents(true);
        ui.centralWidget->setEnabled(true);
        ui.startButton->setEnabled(false);
        });
    QAction* LoadParamsAction = fileMenu->addAction("Load params");     // 设置名字
    QAction* SaveParamsAction = fileMenu->addAction("Save params");     // 设置名字
    ui.templateDilateSpinBox->setValue(templateDilateSize);
    connect(ui.initTemplateButton, &QPushButton::clicked, this, [=]() {
        templatePreprocess();
        Mat showTemplateImg;
        cvtColor(template_curve, showTemplateImg, COLOR_GRAY2BGR);
        QSize labelSize = ui.templateLabel->size();
        labelSize.setWidth(labelSize.width() * 0.9);
        labelSize.setHeight(labelSize.height() * 0.9);
        QImage qtFrame = QImage((const uchar*)showTemplateImg.data, showTemplateImg.cols, showTemplateImg.rows, showTemplateImg.step, QImage::Format_RGB888);
        QPixmap pixmap = QPixmap::fromImage(qtFrame).scaled(labelSize);
        ui.templateLabel->setPixmap(pixmap);
        ui.templateLabel->setScaledContents(true);
        ui.startButton->setEnabled(true);
        });
    qsSrcPath = "";
    qsTemplatePath = "";

    connect(ui.srcPathButton, &QPushButton::clicked, this, [=]() {
        qsSrcPath = QFileDialog::getOpenFileName(this,
            tr(" "),
            "./",
            tr(" "));
        if (qsSrcPath.length() > 0)
        {
            ui.srcImagePath->insertPlainText(qsSrcPath);
        }
        src = imread(qsSrcPath.toStdString(), IMREAD_COLOR);
        if (src.empty())
        {
            QMessageBox::information(this,
                tr("Open Image failed !"),
                tr("Open Image failed !"));
            return;
        }
        srcImg = src.clone();
        QSize labelSize = ui.srcImageLabel->size();
        labelSize.setWidth(labelSize.width() * 0.9);
        labelSize.setHeight(labelSize.height() * 0.9);
        QImage qtFrame = QImage((const uchar*)src.data, src.cols, src.rows, src.step, QImage::Format_RGB888).rgbSwapped();
        //QImage qtFrame = QImage((const uchar*)srcImg.data, srcImg.cols, srcImg.rows, QImage::Format_RGB888);   不能使用这种错误的方式，对某些图片会出错，原因暂时不明
        QPixmap qpImg = QPixmap::fromImage(qtFrame).scaled(labelSize);
        ui.srcImageLabel->setPixmap(qpImg);
        ui.srcImageLabel->setScaledContents(true);
        //this->update();
        changeDownSampleScale(0);
        updateResault();
        //ui.statusBar->showMessage("Src preprocess thread start ");
        });


    /*connect(ui.invertTemplateCheckBox, &QCheckBox::clicked, this, [=]() {
        if (ui.invertTemplateCheckBox->isChecked())
            threshold(templateImg, templateImg, constThreshold, 255, THRESH_BINARY_INV);
        else
            threshold(templateImg, templateImg, constThreshold, 255, THRESH_BINARY);
        Mat showTemplateImg;
        cvtColor(templateImg, showTemplateImg, COLOR_GRAY2BGR);
        QSize labelSize = ui.templateLabel->size();
        labelSize.setWidth(labelSize.width() * 0.9);
        labelSize.setHeight(labelSize.height() * 0.9);
        QImage qtFrame = QImage((const uchar*)showTemplateImg.data, showTemplateImg.cols, showTemplateImg.rows, showTemplateImg.step, QImage::Format_RGB888);
        QPixmap pixmap = QPixmap::fromImage(qtFrame).scaled(labelSize);
        ui.templateLabel->setPixmap(pixmap);
        ui.templateLabel->setScaledContents(true);
        });*/

    ui.redLSpinBox->setValue(lowThreshold.val[0]);
    ui.greenLSpinBox->setValue(lowThreshold.val[1]);
    ui.blueLSpinBox->setValue(lowThreshold.val[2]);
    ui.redHSpinBox->setValue(highThreshold.val[0]);
    ui.greenHSpinBox->setValue(highThreshold.val[1]);
    ui.blueHSpinBox->setValue(highThreshold.val[2]);
    connect(ui.redLSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeThreshold(int)));
    connect(ui.greenLSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeThreshold(int)));
    connect(ui.blueLSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeThreshold(int)));
    connect(ui.redHSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeThreshold(int)));
    connect(ui.greenHSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeThreshold(int)));
    connect(ui.blueHSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeThreshold(int)));

    ui.DownSampleSpinBox->setValue(downSampleScale);
    //connect(ui.DownSampleSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeThreshold(int)));
    connect(ui.DownSampleSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeDownSampleScale(int)));
    ui.scaleStepSpinBox->setValue(scaleStep);
    ui.rotateStepSpinBox->setValue(rotateStep);
    ui.poolSizeSpinBox->setValue(poolSize);

    matchThread = new QtMatchThread;
    connect(matchThread, SIGNAL(FinishMatching(cv::Mat*)), this, SLOT(GetMatchResault(cv::Mat*)));
    //connect(matchThread, SIGNAL(FinishMatching()), this, SLOT(GetMatchResault()));
    connect(matchThread, SIGNAL(UpdateMatchStatus(int, int)), this, SLOT(GetMatchStatus(int, int)));
    connect(ui.startButton, &QPushButton::clicked, this, [=]() {
        vector<Mat>srcParams, templateParams;
        srcParams.push_back(srcImg.clone());
        srcParams.push_back(srcBinMat.clone());
        templateParams.push_back(template_curve.clone());
        templateParams.push_back(outsideCurve.clone());
        templateParams.push_back(outsideCurveMask.clone());

        matchThread->setParams(srcParams, templateParams, scaleStep, rotateStep, poolSize);
        matchThread->start();
        ui.centralWidget->setEnabled(false);
        ui.statusBar->showMessage("Start match task", statusBarTimeout);
        });
}

shoesGUI::~shoesGUI()
{

}

void shoesGUI::changeThreshold(int tmp)
{
    if (srcImg.empty())
    {
        return;
    }
    lowThreshold.val[0] = ui.redLSpinBox->value();
    lowThreshold.val[1] = ui.greenLSpinBox->value();
    lowThreshold.val[2] = ui.blueLSpinBox->value();
    highThreshold.val[0] = ui.redHSpinBox->value();
    highThreshold.val[1] = ui.greenHSpinBox->value();
    highThreshold.val[2] = ui.blueHSpinBox->value();
    srcBinMat = Mat::zeros(srcImg.size(), CV_8UC1);
    inRange(srcImg, lowThreshold, highThreshold, srcBinMat);
    resaultImg = srcBinMat.clone();
    updateResault();
}

void shoesGUI::changeDownSampleScale(int tmp)
{
    if (srcImg.empty())
    {
        return;
    }
    downSampleScale = ui.DownSampleSpinBox->value();
    srcImg = src.clone();
    if (downSampleScale > 0)
    {
        for (int i = 0; i < downSampleScale; i++)
            pyrDown(srcImg, srcImg);
    }
    changeThreshold(0);
}

void shoesGUI::GetMatchResault(Mat* resaultMat)
{

    if (resaultMat == NULL)
        return;

    resaultImg = resaultMat->clone();
    updateResault();
    ui.statusBar->showMessage("Finish match and seal", statusBarTimeout);
    delete resaultMat;
    ui.centralWidget->setEnabled(true);
}

void shoesGUI::GetMatchResault()
{
    ui.statusBar->showMessage("Finish match and seal", statusBarTimeout);
}

void shoesGUI::GetMatchStatus(int status_code, int param)
{
    QString message;
    switch (status_code)
    {
    case 0:
        ui.detectNumLabel->setText(QString(to_string(param).c_str()));
        ui.statusBar->showMessage("Finish src preprocess", statusBarTimeout);
        break;
    case 1:
        message = QString("Finish Match Pyramid building size=") + QString(to_string(param).c_str());
        ui.statusBar->showMessage(message, statusBarTimeout);
        break;
    default:
        break;
    }
}



void shoesGUI::updateResault()
{
    if (resaultImg.empty())
        return;
    Mat showImg;
    if (resaultImg.channels() == 1)
        cvtColor(resaultImg, showImg, COLOR_GRAY2BGR);
    else
        showImg = resaultImg.clone();
    QSize labelSize = ui.resaultLabel->size();
    labelSize.setWidth(labelSize.width() * 0.9);
    labelSize.setHeight(labelSize.height() * 0.9);
    QImage qtFrame = QImage((const uchar*)showImg.data, showImg.cols, showImg.rows, showImg.step, QImage::Format_RGB888).rgbSwapped();
    QPixmap pixmap = QPixmap::fromImage(qtFrame).scaled(labelSize);
    ui.resaultLabel->setPixmap(pixmap);
    ui.resaultLabel->setScaledContents(true);
    ui.statusBar->showMessage("Update resault image", statusBarTimeout);
}

void shoesGUI::srcPreprocess()
{

    
}

void shoesGUI::templatePreprocess()
{
    if (ui.invertTemplateCheckBox->isChecked())
        threshold(templateImg, template_curve, constThreshold, 255, THRESH_BINARY_INV);
    else
        threshold(templateImg, template_curve, constThreshold, 255, THRESH_BINARY);
    int elememtSize = ui.templateDilateSpinBox->value();
    if (elememtSize > 1)
    {
        Mat element = getStructuringElement(MORPH_RECT, Size(elememtSize, elememtSize));
        morphologyEx(template_curve, template_curve, MORPH_DILATE, element);
    }
    outsideCurve = Mat::zeros(templateImg.size(), CV_8UC1);
    outsideCurveMask = Mat::zeros(templateImg.size(), CV_8UC1);
    vector<vector<Point>>outsidePoints;
    findContours(template_curve, outsidePoints, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
    int drawOutCurve = elememtSize < 7 ? 7 : elememtSize + 4;
    drawContours(outsideCurve, outsidePoints, -1, Scalar::all(255), drawOutCurve);
    drawContours(template_curve, outsidePoints, -1, Scalar::all(150), drawOutCurve);
    drawContours(outsideCurveMask, outsidePoints, -1, Scalar::all(255), -1);
}
